#!/usr/bin/env python3
"""
漫画打包工具
将指定目录下的每个子文件夹打包为独立的ZIP压缩包
"""

import os
import sys
import argparse
import zipfile
from pathlib import Path
from typing import List, Optional

from loguru import logger
from tqdm import tqdm


def setup_logger() -> None:
    """
    配置loguru日志记录器
    设置日志格式和输出级别
    """
    logger.remove()  # 移除默认处理器
    logger.add(
        sys.stderr,
        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
        level="INFO"
    )
    logger.add(
        "manga_package.log",
        format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
        level="DEBUG",
        rotation="10 MB"
    )


def get_work_directory() -> Path:
    """
    从命令行参数或环境变量获取工作目录路径
    
    Returns:
        Path: 工作目录路径对象
        
    Raises:
        SystemExit: 当无法获取有效工作目录时退出程序
    """
    parser = argparse.ArgumentParser(description="漫画打包工具")
    parser.add_argument(
        "-d", "--directory",
        type=str,
        help="工作目录路径"
    )
    
    args = parser.parse_args()
    
    # 优先使用命令行参数
    work_dir = args.directory
    
    # 如果命令行参数为空，尝试从环境变量获取
    if not work_dir:
        work_dir = os.getenv("MANGA_WORK_DIR")
    
    if not work_dir:
        logger.error("未指定工作目录。请使用 -d 参数或设置 MANGA_WORK_DIR 环境变量")
        sys.exit(1)
    
    work_path = Path(work_dir)
    
    if not work_path.exists():
        logger.error(f"工作目录不存在: {work_path}")
        sys.exit(1)
    
    if not work_path.is_dir():
        logger.error(f"指定路径不是目录: {work_path}")
        sys.exit(1)
    
    logger.info(f"工作目录: {work_path.absolute()}")
    return work_path


def get_subdirectories(work_dir: Path) -> List[Path]:
    """
    获取工作目录下的所有子文件夹
    
    Args:
        work_dir: 工作目录路径
        
    Returns:
        List[Path]: 子文件夹路径列表
    """
    subdirs = []
    
    try:
        for item in work_dir.iterdir():
            if item.is_dir():
                subdirs.append(item)
                logger.debug(f"发现子目录: {item.name}")
    except PermissionError as e:
        logger.error(f"无权限访问目录 {work_dir}: {e}")
        return []
    except Exception as e:
        logger.error(f"遍历目录时发生错误 {work_dir}: {e}")
        return []
    
    logger.info(f"共发现 {len(subdirs)} 个子目录")
    return sorted(subdirs)


def get_files_in_directory(directory: Path) -> List[Path]:
    """
    获取指定目录下的所有文件
    
    Args:
        directory: 目录路径
        
    Returns:
        List[Path]: 文件路径列表
    """
    files = []
    
    try:
        for item in directory.iterdir():
            if item.is_file():
                files.append(item)
                logger.debug(f"发现文件: {item.name}")
    except PermissionError as e:
        logger.error(f"无权限访问目录 {directory}: {e}")
        return []
    except Exception as e:
        logger.error(f"遍历目录时发生错误 {directory}: {e}")
        return []
    
    return sorted(files)


def create_zip_package(source_dir: Path, output_dir: Path) -> bool:
    """
    将源目录中的所有文件打包为ZIP压缩包
    
    Args:
        source_dir: 源文件夹路径
        output_dir: 输出目录路径
        
    Returns:
        bool: 打包是否成功
    """
    zip_filename = f"{source_dir.name}.zip"
    zip_path = output_dir / zip_filename
    
    # 获取源目录中的所有文件
    files = get_files_in_directory(source_dir)
    
    if not files:
        logger.warning(f"目录 {source_dir.name} 中没有文件，跳过打包")
        return False
    
    try:
        with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 使用tqdm显示当前目录的文件打包进度
            for file_path in tqdm(files, desc=f"打包 {source_dir.name}", unit="文件", leave=False):
                try:
                    # 将文件直接添加到ZIP根目录，不保留文件夹结构
                    zipf.write(file_path, file_path.name)
                    logger.debug(f"已添加文件: {file_path.name}")
                except Exception as e:
                    logger.error(f"添加文件 {file_path.name} 到ZIP时发生错误: {e}")
                    return False
        
        logger.info(f"成功创建压缩包: {zip_path} (包含 {len(files)} 个文件)")
        return True
        
    except Exception as e:
        logger.error(f"创建ZIP文件 {zip_path} 时发生错误: {e}")
        if zip_path.exists():
            try:
                zip_path.unlink()  # 删除不完整的ZIP文件
                logger.info(f"已删除不完整的ZIP文件: {zip_path}")
            except Exception as cleanup_error:
                logger.error(f"删除不完整ZIP文件时发生错误: {cleanup_error}")
        return False


def main() -> None:
    """
    主函数：执行漫画打包流程
    """
    setup_logger()
    logger.info("开始执行漫画打包工具")
    
    try:
        # 获取工作目录
        work_dir = get_work_directory()
        
        # 获取所有子目录
        subdirs = get_subdirectories(work_dir)
        
        if not subdirs:
            logger.warning("工作目录中没有子文件夹，程序退出")
            return
        
        # 创建输出目录（在工作目录下创建packages文件夹）
        output_dir = work_dir / "packages"
        output_dir.mkdir(exist_ok=True)
        logger.info(f"输出目录: {output_dir.absolute()}")
        
        # 统计变量
        success_count = 0
        total_count = len(subdirs)
        
        # 使用tqdm显示总体进度
        with tqdm(subdirs, desc="处理目录", unit="目录") as pbar:
            for subdir in pbar:
                pbar.set_postfix({"当前": subdir.name})
                
                logger.info(f"开始处理目录: {subdir.name}")
                
                if create_zip_package(subdir, output_dir):
                    success_count += 1
                    logger.info(f"目录 {subdir.name} 处理完成")
                else:
                    logger.error(f"目录 {subdir.name} 处理失败")
        
        # 输出最终统计结果
        logger.info(f"打包完成！成功: {success_count}/{total_count}")
        
        if success_count == total_count:
            logger.info("所有目录都已成功打包")
        else:
            logger.warning(f"有 {total_count - success_count} 个目录打包失败")
            
    except KeyboardInterrupt:
        logger.warning("用户中断程序执行")
        sys.exit(1)
    except Exception as e:
        logger.error(f"程序执行过程中发生未预期的错误: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()